package com.kly.test.base.adpater

import android.view.View
import android.view.ViewGroup
import androidx.paging.PagedListAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.kly.test.R
import com.kly.test.util.inflate
import java.util.*

const val ID_EMPTY = "id_empty"
const val ID_MORE_RETRY = "id_more_retry"
const val ID_ERROR = "id_error"
const val ID_MORE_LOADING = "id_more_loading" // 其实可以用 负数int类型的
const val ID_NO_MORE = "id_no_more"
const val PAGE_INITIAL = 1
const val PAGE_RESET = PAGE_INITIAL - 1
var itemTypeProvider = 1

data class Cell(
        val type: Int,
        val id: String,
        val argString: String? = null,
        val extra: Any? = null
) {
    inline fun <reified T> data(): T? {
        return extra as? T?
    }

    fun get(): Any? {
        return when (type) {
            ItemType.Unknown -> null
            ItemType.EmptyPlaceHolder -> null
            ItemType.ErrorPlaceHolder -> null
            ItemType.LoadingPlaceHolder -> null
            ItemType.RetryPlaceHolder -> null
            ItemType.NoMorePlaceHolder -> null
            else -> null // usually, can not be there.
//            else -> throw NullPointerException("You should override this function to return item object") // assert
        }
    }
}

typealias AdapterCallback = (action: String, item: Any?) -> Unit

const val ITEM_CLICKED = "adapter_item_clicked"

abstract class BasePagedAdapter : PagedListAdapter<Cell, RecyclerView.ViewHolder>(DIFF) {

    private var listener: AdapterCallback? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ItemType.ErrorPlaceHolder -> ErrorPlaceHolderVH(parent.inflate(R.layout.layout_recycler_error))
            ItemType.EmptyPlaceHolder -> EmptyPlaceHolderVH(parent.inflate(R.layout.layout_recycler_empty))
            ItemType.LoadingPlaceHolder -> MoreLoadingVH(parent.inflate(R.layout.layout_recycler_loading))
            else -> UnknownVH(View(parent.context).apply { layoutParams = ViewGroup.LayoutParams(0, 0) })
        }
    }

    fun setListener(callback: AdapterCallback?) {
        listener = callback
    }

    protected val callback: AdapterCallback = { item, action ->
        listener?.invoke(item, action)
    }

    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        return item?.type ?: ItemType.Unknown
    }
}

private val DIFF = object : DiffUtil.ItemCallback<Cell>() {
    override fun areItemsTheSame(oldItem: Cell, newItem: Cell): Boolean {
        return newItem.type == oldItem.type && newItem.id == oldItem.id
    }

    override fun areContentsTheSame(oldItem: Cell, newItem: Cell): Boolean {
        return newItem.type == oldItem.type &&
                (Objects.equals(newItem.get(), oldItem.get()) && Objects.equals(newItem.data(), oldItem.data()))
    }
}

fun superProcessCell(itemTypeId: String): Cell? {
    return when (itemTypeId) {
        ID_EMPTY -> Cell(ItemType.EmptyPlaceHolder, ID_EMPTY)
        ID_ERROR -> Cell(ItemType.ErrorPlaceHolder, ID_ERROR)
        ID_MORE_LOADING -> Cell(ItemType.LoadingPlaceHolder, ID_MORE_LOADING)
        ID_MORE_RETRY -> Cell(ItemType.RetryPlaceHolder, ID_MORE_RETRY)
        ID_NO_MORE -> Cell(ItemType.NoMorePlaceHolder, ID_NO_MORE)
        else -> null
    }
}

class MoreRetryVH(itemView: View) : RecyclerView.ViewHolder(itemView)
class UnknownVH(itemView: View) : RecyclerView.ViewHolder(itemView)
class ErrorPlaceHolderVH(itemView: View) : RecyclerView.ViewHolder(itemView)
class MoreLoadingVH(itemView: View) : RecyclerView.ViewHolder(itemView)
class NoMoreVH(itemView: View) : RecyclerView.ViewHolder(itemView)
class EmptyPlaceHolderVH(itemView: View) : RecyclerView.ViewHolder(itemView)

object ItemType {
    const val Unknown= -1
    val EmptyPlaceHolder= itemTypeProvider++
    val ErrorPlaceHolder= itemTypeProvider++
    val LoadingPlaceHolder= itemTypeProvider++
    val RetryPlaceHolder= itemTypeProvider++
    val NoMorePlaceHolder= itemTypeProvider++
}
